package pers.hl.library.common.base;

import com.github.pagehelper.PageHelper;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.WebApplicationContext;
import pers.hl.library.common.Const;
import pers.hl.library.common.Response;
import pers.hl.library.utils.ExceptionHelper;

import java.util.Collections;
import java.util.List;

/**
 * Controller基类，统一封装简单的增删改查
 *
 * @param <T> 要操作的实体类（与数据库表对应）
 */
@CrossOrigin(allowCredentials = "true")
@RestController
@Transactional
public abstract class BaseController<T> {

    protected Logger logger = Logger.getLogger(this.getClass().getName());

    @Autowired
    WebApplicationContext applicationContext;

    /**
     * 统一封装的service层
     */
    private IService<T> mService;
    /**
     * 业务模块名称
     */
    protected String mBussName;

    /**
     * 在子类构造函数中通过依赖注入，指明具体的service层
     *
     * @param service 统一service
     */
    public void init(IService<T> service) {
        this.mService = service;
        this.mBussName = getBussName();
    }

    /**
     * 获取业务模块名称
     */
    protected abstract String getBussName();

    /**
     * 增加数据 单个
     *
     * @param data 单个数据
     */
    @PostMapping("add")
    public Response add(@RequestBody T data) throws Exception {
        if (data == null) {
            return Response.fail_400("数据不能为空");
        }
        beforeAdd(data);
        if (mService.addData(data)) {
            afterAdd(data);
            return Response.ok(mBussName + "添加成功", data);
        }
        return Response.fail_500(mBussName + "添加失败");
    }

//    /**
//     * 删除数据 单个
//     * @param id 数据id
//     */
//    @PostMapping("delete")
//    public Response delete(@RequestParam("id") Integer id) {
//        if (id == null || id <= 0) {
//            return Response.fail_400("id参数错误，必须大于0");
//        }
//        if (service.deleteData(id)) {
//            return Response.ok();
//        }
//        return Response.fail_500();
//    }

    /**
     * 删除数据 批量
     *
     * @param ids 数据id集合
     */
    @DeleteMapping("delete")
    public Response batchDelete(@RequestBody List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Response.fail_400("id参数不能为空");
        }
        if (mService.batchDelete(ids)) {
            return Response.ok(mBussName + "删除成功");
        }
        return Response.fail_500(mBussName + "删除失败");
    }

    /**
     * 修改数据 单个
     *
     * @param data 单个数据
     */
    @PostMapping("update")
    public Response update(@RequestBody T data) throws Exception {
        if (data == null) {
            return Response.fail_400("数据不能为空");
        }
        beforeUpdate(data);
        if (mService.updateSelective(data)) {
            afterUpdate(data);
            return Response.ok(mBussName + "更新成功");
        }
        return Response.fail_500(mBussName + "更新失败");
    }

    /**
     * 根据id查询单个数据
     *
     * @param id 数据id
     */
    @GetMapping("{id}")
    public Response getSingle(@PathVariable Integer id) {
        if (id == null || id <= 0) {
            return Response.fail_400("id参数错误，必须大于0");
        }
        T data = mService.getDataByPrimaryId(id);
        if (data == null) {
            ExceptionHelper.throw404("未找到" + getBussName());
        }
        afterGetDataByPrimaryId(data);
        return Response.ok(data);
    }

    protected void afterGetDataByPrimaryId(T data) {

    }

    /**
     * 根据其他id查询单个数据
     *
     * @param id 其他唯一id
     */
    @GetMapping("data/{id}")
    public Response getSingleByOtherId(@PathVariable Integer id) {
        if (id == null || id <= 0) {
            return Response.fail_400("id参数错误，必须大于0");
        }
        T data = mService.getDataByOtherId(id);
        return Response.ok(data);
    }

    /**
     * 根据id查询数据集合方式A
     *
     * @param key      查询业务字段
     * @param otherId  其他非主键id
     * @param pageSize 单页数量
     * @param pageNum  页码
     */
    @GetMapping("list/{key}/{otherId}")
    public Response getList(@PathVariable String key, @PathVariable Integer otherId,
                            @RequestParam(required = false, value = "pageSize") Integer pageSize,
                            @RequestParam(required = false, value = "pageNum") Integer pageNum) {
        if (otherId == null || otherId < 0) {
            return Response.fail_400("id参数不能为空");
        }
        beforeQuery(pageNum, pageSize);
        List<T> list = mService.getDataList(key, otherId);
        return Response.ok(list);
    }

    /**
     * 根据字段查询数据集合方式B
     *
     * @param key      查询业务字段
     * @param value    值
     * @param pageSize 单页数量
     * @param pageNum  页码
     */
    @GetMapping("listByKey/{key}/{value}")
    public Response getList(@PathVariable String key, @PathVariable String value,
                            @RequestParam(required = false, value = "pageSize") Integer pageSize,
                            @RequestParam(required = false, value = "pageNum") Integer pageNum) {
        if (StringUtils.isEmpty(key)) {
            return Response.fail_400("key参数不能为空");
        }
        if (StringUtils.isEmpty(value)) {
            return Response.fail_400("value参数不能为空");
        }
        beforeQuery(pageNum, pageSize);
        List<T> list = mService.getDataList2(key, value);
        return Response.ok(notNullList(list));
    }

    /**
     * 在查询前的操作,用于分页
     *
     * @param pageNum  页码
     * @param pageSize 分页数量
     */
    protected void beforeQuery(Integer pageNum, Integer pageSize) {
        if (pageNum == null || pageSize == null) {
            pageNum = Const.PageParams.DEFAULT_PAGE_NUM;
            pageSize = Const.PageParams.DEFAULT_PAGE_SIZE;
        }
        if (pageNum < 0 || pageSize < 0) {
            pageNum = Const.PageParams.DEFAULT_PAGE_NUM;
            pageSize = Const.PageParams.DEFAULT_PAGE_SIZE;
        }
        PageHelper.startPage(pageNum, pageSize);
    }

    /**
     * 在新增之前做的操作
     *
     * @param data 待新增的数据
     */
    protected void beforeAdd(T data) throws Exception {

    }

    /**
     * 在新增之后处理数据
     *
     * @param data 待新增的数据
     */
    protected void afterAdd(T data) throws Exception {

    }

    /**
     * 在更新之前做的操作
     *
     * @param data 待更新的数据
     */
    protected void beforeUpdate(T data) throws Exception {

    }

    /**
     * 在更新之后做的操作
     *
     * @param data 待更新的数据
     */
    protected void afterUpdate(T data) throws Exception {

    }

    /**
     * 在删除之后做的操作
     *
     * @param data 待更新的数据
     */
    protected void afterDelete(T data) throws Exception {

    }



    private List<?> notNullList(List<?> list) {
        return ObjectUtils.isEmpty(list) ? Collections.emptyList() : list;
    }

}
